package edu.uob;


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;

public class DataTable {
    private String tableName;
    private final List<String> columnNames;
    private Object[][] data; // 行列合并为一个二维数组
    private int lastId; // 最后一个 id 的值


    public DataTable() {
        // 构造方法
        this.columnNames = new ArrayList<>();
        this.lastId = 0; // 初始化最后一个 id
    }

    // 获取器和设置器

    public List<String> getColumnNames() {
        return this.columnNames;
    }

    // 添加一行
    public void addRow(String rowData) {
        if (this.data == null) {
            // 如果为 null，可能需要进行一些初始化操作，这取决于你的需求
            // 例如，你可以创建一个新的空数据数组
            this.data = new Object[0][];
        }

        rowData = rowData.replaceAll("'", "");

        String[] valuesList = rowData.split(",");
        if (valuesList.length != (this.columnNames.size() - 1)) {
            throw new IllegalArgumentException("rowData中的元素数量必须与列数相匹配。");
        }

        StringJoiner joiner = new StringJoiner("\t");
        joiner.add(String.valueOf(++this.lastId)); // Increment the ID
        for (String value : valuesList) {
            joiner.add(value);
        }
        String newRow = joiner.toString();

        // Create a new array with one more row
        Object[][] newData = new Object[this.data.length + 1][];

        // Copy the contents of the old array to the new array
        System.arraycopy(this.data, 0, newData, 0, this.data.length);

        // Assign the new row data to the last element of newData
        newData[newData.length - 1] = newRow.split("\t");

        // Update the reference to point to the newData array
        this.data = newData;
    }

    public String displayDataToString() {
        StringBuilder result = new StringBuilder();

        if (this.data != null) {
            // Print the column names
            result.append("Column Names:\n");
            for (int i = 0; i < this.columnNames.size(); i++) {
                result.append(this.columnNames.get(i));
                if (i < this.columnNames.size() - 1) {
                    result.append("\t");
                }
            }
            result.append("\n");

            // Print the data
            for (Object[] rowData : this.data) {
                for (int i = 0; i < rowData.length; i++) {
                    result.append(rowData[i]);
                    if (i < rowData.length - 1) {
                        result.append("\t");
                    }
                }
                result.append("\n");
            }
        } else {
            result.append("Data is empty.\n");
        }
        return result.toString();
    }

    public void dispose() {
        // 清空列名列表
        this.columnNames.clear();

        // 清空数据
        this.data = null;

        // 重置最后一个 id
        this.lastId = 0;

        // 清空表名
        this.tableName = null;
    }

    // 更新数据
    public void updateData(int rowIndex, int columnIndex, Object value) {
        if (this.data != null && rowIndex >= 0 && rowIndex < this.data.length && columnIndex >= 0 && columnIndex < this.columnNames.size()) {
            this.data[rowIndex][columnIndex] = value;
        } else {
            throw new IllegalArgumentException("指定的行索引或列索引无效。");
        }
    }

    public String writeDataToFile(Path path) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(path.toFile()))) {
            // 写入列名
            for (int i = 0; i < this.columnNames.size(); i++) {
                writer.write(this.columnNames.get(i));
                if (i < this.columnNames.size() - 1) {
                    writer.write("\t");
                }
            }
            writer.write("\n");

            // 写入数据行
            if (this.data != null) {
                for (Object[] rowData : this.data) {
                    for (int i = 0; i < rowData.length; i++) {
                        writer.write(rowData[i].toString());
                        if (i < rowData.length - 1) {
                            writer.write("\t");
                        }
                    }
                    writer.write("\n");
                }
            }
            return "[OK]";
        } catch (IOException e) {
            return "[ERROR]: Error writing data to file: " + e.getMessage();
        }
    }

    public String getTableName() {
        return this.tableName;
    }

    public void setTableName(String tableName1) {
        this.tableName = tableName1;
    }

    public Object[][] getData() {
        return this.data;
    }

    public void loadRow(Object[] rowData) {
        // 如果 rowData 的长度小于列数，将空值 "" 添加到 rowData 的末尾，直到长度与列数相等
        if (rowData.length < this.columnNames.size()) {
            Object[] newRowData = new Object[this.columnNames.size()];
            System.arraycopy(rowData, 0, newRowData, 0, rowData.length);
            for (int i = rowData.length; i < this.columnNames.size(); i++) {
                newRowData[i] = ""; // 添加空值
            }
            rowData = newRowData;
        }

        if (this.data == null) {
            this.data = new Object[1][this.columnNames.size()]; // 第一行
            this.data[0] = rowData;
        } else {
            Object[][] newData = new Object[this.data.length + 1][this.columnNames.size()];
            System.arraycopy(this.data, 0, newData, 0, this.data.length);
            newData[this.data.length] = rowData;
            this.data = newData;
        }

    }

    // 删除行
    public void deleteRow(int rowIndex) {
        if (this.data != null && rowIndex >= 0 && rowIndex < this.data.length) {
            Object[][] newData = new Object[this.data.length - 1][this.columnNames.size()];
            System.arraycopy(this.data, 0, newData, 0, rowIndex);
            System.arraycopy(this.data, rowIndex + 1, newData, rowIndex, this.data.length - rowIndex - 1);
            this.data = newData;
        } else {
            throw new IllegalArgumentException("指定的行索引无效。");
        }
    }

    // 查找行索引
    public int[] findRowIndex(Object value) {
        if (this.data != null) {
            for (int i = 0; i < this.data.length; i++) {
                for (int j = 0; j < this.columnNames.size(); j++) {
                    if (this.data[i][j].equals(value)) {
                        return new int[]{i, j}; // 返回行和列索引的数组
                    }
                }
            }
        }
        return new int[]{-1, -1}; // 未找到
    }

    // 添加列名
    public void addColumnName(String columnName) {
        this.columnNames.add(columnName);
        if (this.data != null) {
            for (int i = 0; i < this.data.length; i++) {
                Object[] newRow = new Object[this.data[i].length + 1];
                System.arraycopy(this.data[i], 0, newRow, 0, this.data[i].length);
                newRow[this.data[i].length] = null; // 新列置为 null
                this.data[i] = newRow;
            }
        }
    }


    // 删除列名
    public void deleteColumnName(String columnName) {
        if (!this.columnNames.contains(columnName)) {
            throw new IllegalArgumentException("列名不存在。");
        }
        int columnIndex = this.columnNames.indexOf(columnName);
        this.columnNames.remove(columnName);
        if (this.data != null) {
            for (int i = 0; i < this.data.length; i++) {
                Object[] newRow = new Object[this.data[i].length - 1];
                System.arraycopy(this.data[i], 0, newRow, 0, columnIndex);
                System.arraycopy(this.data[i], columnIndex + 1, newRow, columnIndex, this.data[i].length - columnIndex - 1);
                this.data[i] = newRow;
            }
        }
    }

    public void loadDataFromPath(Path path) throws IOException {
        try (BufferedReader br = Files.newBufferedReader(path)) {
            String line;
            boolean firstLine = true;
            while ((line = br.readLine()) != null) {
                String[] rowData = line.split("\t");
                if (firstLine) { // Processing column names
                    firstLine = false;
                    // Setting table name to the name of the last file in the path without the .tab extension
                    String[] pathParts = path.toString().split("\\\\"); // Splitting by backslash on Windows
                    String fileName = pathParts[pathParts.length - 1];
                    if (fileName.endsWith(".tab")) {
                        this.tableName = fileName.substring(0, fileName.length() - 4);
                    } else {
                        this.tableName = fileName;
                    }
                    // Adding column names to DataTable
                    for (String columnName : rowData) {
                        addColumnName(columnName);
                    }
                } else { // Processing data rows
                    // Getting the ID from the data row and updating the lastId in DataTable
                    int id = Integer.parseInt(rowData[0]);
                    if (id > this.lastId) {
                        this.lastId = id;
                    }
                    loadRow(rowData);
                }
            }
        }
    }

    public Object[] getColumnData(int columnIndex) {
        if (this.data == null || columnIndex < 0 || columnIndex >= this.columnNames.size()) {
            throw new IllegalArgumentException("Invalid column index or no data available.");
        }

        Object[] columnData = new Object[this.data.length];
        for (int i = 0; i < this.data.length; i++) {
            columnData[i] = this.data[i][columnIndex];
        }
        return columnData;
    }

    public void deleteColumn(String columnName) {
        if (!this.columnNames.contains(columnName)) {
            throw new IllegalArgumentException(this.columnNames+"  "+columnName+ " Column name does not exist. " );
        }

        int columnIndex = this.columnNames.indexOf(columnName);
        this.columnNames.remove(columnName);

        if (this.data != null) {
            for (int i = 0; i < this.data.length; i++) {
                Object[] newRow = new Object[this.data[i].length - 1];
                System.arraycopy(this.data[i], 0, newRow, 0, columnIndex);
                System.arraycopy(this.data[i], columnIndex + 1, newRow, columnIndex, this.data[i].length - columnIndex - 1);
                this.data[i] = newRow;
            }
        }
    }
}
